/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.bpm.engine.impl.cmd;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.bpm.core.model.BpmnModel;
import com.je.bpm.core.model.FlowElement;
import com.je.bpm.core.model.task.KaiteRandomUserTask;
import com.je.bpm.engine.ActivitiException;
import com.je.bpm.engine.delegate.DelegateExecution;
import com.je.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import com.je.bpm.engine.impl.context.Context;
import com.je.bpm.engine.impl.interceptor.CommandContext;
import com.je.bpm.engine.impl.persistence.entity.ExecutionEntity;
import com.je.bpm.engine.impl.persistence.entity.ExecutionEntityManager;
import com.je.bpm.engine.impl.persistence.entity.RandomTaskEntity;
import com.je.bpm.engine.impl.persistence.entity.TaskEntity;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static com.je.bpm.engine.impl.bpmn.behavior.KaiteBaseUserTaskActivityBehavior.RANDOM_TASK_ASSIGNEE;
import static java.util.stream.Collectors.toList;

//随机节点委托、转办获取人员信息
public class RandomTaskDelegateTransferGetUserInfoCmd extends NeedsActiveTaskCmd<Object> {
    private static final long serialVersionUID = 1L;

    protected String piId;
    /**
     * 指派人
     */
    private String assignee;

    public RandomTaskDelegateTransferGetUserInfoCmd(String taskId, String piId, String assignee) {
        super(taskId, null, null);
        this.piId = piId;
        this.assignee = assignee;
    }


    @Override
    protected Object execute(CommandContext commandContext, TaskEntity task) {
        BpmnModel bpmnModel = commandContext.getProcessEngineConfiguration().getRepositoryService().getBpmnModel(task.getProcessDefinitionId());

        FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        if (flowElement == null) {
            throw new ActivitiException(String.format("Can't find task %s definiton from the process.", task.getName()));
        }
        String userIds = getRandomTaskUserIds(flowElement, commandContext, task);
        return userIds;
    }

    public String getRandomTaskUserIds(FlowElement flowElement, CommandContext commandContext, TaskEntity task) {
        KaiteRandomUserTask kaiteRandomUserTask = (KaiteRandomUserTask) flowElement;
        String executionId = task.getExecutionId();
        ExecutionEntityManager executionEntityManager = commandContext.getProcessEngineConfiguration().getExecutionEntityManager();
        DelegateExecution execution = executionEntityManager.findById(executionId);
        //（因为存在取回。退回。驳回的情况）先从变量中获取随机节点人员信息 todo
        Object randomTaskAssignee = execution.getVariable(RANDOM_TASK_ASSIGNEE);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
        BpmnModel bpmnModel = processEngineConfiguration.getRepositoryService().getBpmnModel(task.getProcessDefinitionId());
        //获取流程的key
        String processKey = bpmnModel.getProcesses().get(0).getId();
        List<RandomTaskEntity> randomTaskEntityList = commandContext.getProcessEngineConfiguration().getRandomTaskDataManager().selectRandomByProcessKeyAndFlowElementIdOrderByCount(processKey, kaiteRandomUserTask.getId());
        if (randomTaskEntityList != null && randomTaskEntityList.size() > 0) {
            RandomTaskEntity randomTaskEntity = null;
            //随机节点，转办和委托过滤掉自己
            List<RandomTaskEntity> randomTaskEntityListNew = randomTaskEntityList.stream().filter(RandomTaskEntity -> !(RandomTaskEntity.getUserId().equals(assignee))).collect(toList());
            if (randomTaskEntityListNew != null && randomTaskEntityListNew.size() > 0) {
                randomTaskEntityList = randomTaskEntityListNew;
            }
            System.out.println("排序前结果：" + randomTaskEntityList.toString());
            Collections.sort(randomTaskEntityList, (o1, o2) -> o2.getCountNum().compareTo(o1.getCountNum()));
            System.out.println("排序后结果：" + randomTaskEntityList.toString());
            String countNum = randomTaskEntityList.get(randomTaskEntityList.size() - 1).getCountNum();
            //获取执行最少次数相同的的集合，在其中随机选一个
            List<RandomTaskEntity> list = null;
            list = randomTaskEntityList.stream().filter((RandomTaskEntity a) -> a.getCountNum().equals(countNum)).collect(toList());
            System.out.println("排序后执行数量最小的结果：" + list.toString());
            int a = (int) (Math.random() * list.size());
            randomTaskEntity = list.get(a);

            if (randomTaskEntity != null) {
                //修改执行人执行次数
                randomTaskEntity.setCountNum(String.valueOf(Long.parseLong(randomTaskEntity.getCountNum()) + 1));
                String time = simpleDateFormat.format(new Date());
                randomTaskEntity.setTime(time);
                commandContext.getProcessEngineConfiguration().getRandomTaskDataManager().update(randomTaskEntity);
                //随机节点处理人加入变量
                addVariable(piId, randomTaskAssignee, kaiteRandomUserTask.getId(), randomTaskEntity.getUserId(), execution);

                return randomTaskEntity.getUserId();
            } else {
                throw new ActivitiException("获取人员信息异常!");
            }
        } else {
            throw new ActivitiException("获取人员信息异常!");
        }

    }

    private void addVariable(String piId, Object randomTaskAssignee, String taskId, String userId, DelegateExecution execution) {
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(piId + "-" + taskId, userId);
        jsonArray.add(jsonObject);
        ExecutionEntity executionEntity = (ExecutionEntity) execution;
        if (randomTaskAssignee != null) {
            JSONArray taskAssignee = JSONArray.parseArray(randomTaskAssignee.toString());
            for (int i = 0; i < taskAssignee.size(); i++) {
                JSONObject taskAssigneeObj = taskAssignee.getJSONObject(i);
                if (!Strings.isNullOrEmpty(taskAssigneeObj.getString(piId + "-" + taskId))) {
                    taskAssigneeObj.put(piId + "-" + taskId, userId);
                } else {
                    taskAssignee.add(jsonObject);
                }
            }
        } else {
            executionEntity.getProcessInstance().setVariable(RANDOM_TASK_ASSIGNEE, jsonArray.toString());
        }
    }
}
